home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / PowerPlant / AGA Classes 1.2 / IndexTabs / LAGAIndexTab.cp < prev    next >
Encoding:
Text File  |  1996-06-30  |  14.4 KB  |  508 lines  |  [TEXT/CWIE]

  1. // ===========================================================================
  2. //    LAGAIndexTab.cp
  3. // ===========================================================================
  4. //    “Apple Grayscale Appearance” compliant Index Tabs
  5. //    Copyright © 1996 Chrisoft (Christophe ANDRES)  All rights reserved.
  6. //
  7. //    You may use this source code in any application (commercial, shareware, freeware,
  8. //    postcardware, etc), but not remove this notice (no need to acknowledge the use of
  9. //    this class in the about box)
  10. //    You may not sell this source code in any form. This source code may be placed on 
  11. //    publicly accessable archive sites and source code disks. It may not be placed on 
  12. //    profit archive sites and source code disks without the permission of the author, 
  13. //    Christophe ANDRES.
  14. //    
  15. //        This source code is distributed in the hope that it will be useful,
  16. //        but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. //        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18. //
  19. //    If you make any change or improvement on this class, please send the improved/changed
  20. //    version to : chrisoft@calva.net or Christophe ANDRES
  21. //                                     20, rue Prosper Mérimée
  22. //                                     67100 STRASBOURG
  23. //                                     FRANCE
  24. //
  25. // ===========================================================================
  26. //    LAGAIndexTab.h            <- double-click + Command-D to see classes declaration
  27. //
  28. //    LAGAIndexTab is my implementation of the “Apple Grayscale Appearance for System 7.5”
  29. //        Index Tabs. Index Tabs where not defined in this document, but some pictures where
  30. //        found in the March 1996 issue of “Apple Directions” pages 16 and 18.
  31. //        LAGAIndexTab relies on view scrolling to perform its switch between differents tabs.
  32. //        mTabbedViewID is a reference to a view that is embeddedin the LAGAIndexTab.
  33. //        This tabbed view has to be placed at least at 21 pixels from the top of LAGAIndexTab,
  34. //        and must leave at least 1 pixel on each side (left, right and bottom).
  35. //        the LAGAIndexTab will use the vertical scroll unit of the tabbed view to perform its
  36. //        tab switch (adapt also the image size height accordingly).
  37. //        This means that all tab elements are always present (although only one is visible)
  38. //        and the switch between tabs is very fast.
  39. //
  40. //        Index Tabs are not suitable for large number of tabs, so LAGAIndexTab will display only
  41. //        the Index Tabs fitting in the view size.
  42. //
  43. //        An alternate way of using the index tabs is by NOT setting mTabbedViewID (nil) and to
  44. //        override LAGAIndexTab::AdaptTab to perform whatever is needed
  45. //
  46. //    LSTRxAGAIndexTab is a subclass of LAGAIndexTab, which reads the name of its tabs from a
  47. //        'STR#' resource
  48. //
  49. //        This class requires AGAColors.cp to be present in your project
  50. //
  51. //
  52. //        Version : 1.2
  53. //
  54. //        Change History (most recent first, date in US form : mm/dd/yy):
  55. //
  56. //                        06/30/96    ca        Public release of version 1.2
  57. //                        06/04/96    ca        Added RegisterClass method to ease registry
  58. //                                                        Increased version to 1.2
  59. //                        05/16/96    ca        Increased version to 1.1
  60. //                                                        Replaced UEnvironment::HasFeature(env_SupportsColor) with PaneInColor
  61. //                                                        Added change history
  62. //                        04/22/96    ca        class made available by Christophe ANDRES <chrisoft@calva.net>
  63. //                                                        (version 1.0)
  64. //
  65. //        To Do:
  66. //                        Remove hardcoded maximum tabs and use some sort of dynamic list
  67. //
  68.  
  69.  
  70. #include "LAGAIndexTab.h"
  71. #include "AGAColors.h"
  72. #include <URegistrar.h>
  73. #include <LStream.h>
  74.  
  75. //-------Private constants--------------------------------------------------------------------------------------------
  76.  
  77. #define    kTagHeigth                                                    20
  78. #define    kTagTextPosition                                        15
  79. #define    kTagWidthOffset                                            40    //    Leave 20 pixels on each side of the selected title
  80.  
  81. //------Global initialization-----------------------------------------------------------------------------------------
  82.  
  83. void RegisterAGAIndexTab ()
  84.  
  85. {
  86.     //    Registration of LAGAIndexTab
  87.     LAGAIndexTab::RegisterClass();
  88.     //    Registration of LSTRxIndexTabView
  89.     URegistrar::RegisterClass(LSTRxAGAIndexTab::class_ID, (ClassCreatorFunc)LSTRxAGAIndexTab::CreateSTRxAGAIndexTabStream);
  90. }
  91.  
  92. //    begin    <06/04/96    ca>
  93. void LAGAIndexTab::RegisterClass ()
  94.  
  95. {
  96.     URegistrar::RegisterClass(LAGAIndexTab::class_ID, (ClassCreatorFunc)LAGAIndexTab::CreateAGAIndexTabStream);
  97. }
  98. //    end    <06/04/96    ca>
  99.  
  100. LAGAIndexTab* LAGAIndexTab::CreateAGAIndexTabStream (LStream *inStream)
  101.  
  102. {
  103.     return (new LAGAIndexTab(inStream));
  104. }
  105.  
  106. //-------Constructors-------------------------------------------------------------------------------------------------
  107.  
  108. LAGAIndexTab::LAGAIndexTab ()
  109.  
  110. {
  111.     this->InitIndexTab();
  112.     
  113.     mTabbedViewID = 0;
  114.     mTextTraitsID = -1;
  115. }
  116.  
  117. LAGAIndexTab::LAGAIndexTab (LStream    *inStream) : LView(inStream)
  118.  
  119. {
  120.     UInt32 theData;
  121.     
  122.     inStream->ReadData(&theData, sizeof(UInt32));
  123.     mTabbedViewID = theData;
  124.     inStream->ReadData(&mTextTraitsID, sizeof(ResIDT));
  125.     
  126.     this->InitIndexTab();
  127. }
  128.  
  129. void LAGAIndexTab::InitIndexTab ()
  130.  
  131. {
  132.     mTabNumber = 1;                        //    There is always at least one index tab
  133.     mWasSelectedTab = -1;
  134.     mSelectedTab = 0;
  135.     mTabTitle[0] = "\p";
  136.     for (int i = 0;i < kMaxTabs; i++)
  137.         mTabTitleWidth[i] = -1;    //    -1 means that the width has to be calculated again
  138. }
  139.  
  140. //-------Drawers----------------------------------------------------------------------------------------------------
  141.  
  142. void LAGAIndexTab::DrawSelf ()
  143.  
  144. {
  145.     Boolean hasColor = ::PaneInColor(this);                                                                                        //    <05/16/96    ca>
  146.     
  147.     if (IsVisible())
  148.         {
  149.             StColorPenState theState;
  150.             Rect workRect;
  151.             StTextState theTState;
  152.     
  153.             //    set our font informations
  154.             Int16 just = UTextTraits::SetPortTextTraits(mTextTraitsID);
  155.  
  156.             //    Check if we need to calculate the withs of the index tabs
  157.             for (int i = 0;i < mTabNumber; i++)
  158.                 if (mTabTitleWidth[i] == -1)
  159.                     {
  160.                         this->CalculateTitleWidths();
  161.                         break;
  162.                     }
  163.     
  164.             theState.Normalize();
  165.             CalcLocalFrameRect(workRect);
  166.             workRect.bottom--;
  167.             workRect.right--;
  168.     
  169.             //    First lets draw the rest of the frame, excluding the tabs
  170.             ::MoveTo(workRect.left, workRect.top + kTagHeigth + 1);
  171.             ::LineTo(workRect.left, workRect.bottom - 2);
  172.             ::MoveTo(workRect.left + 1, workRect.bottom -1);
  173.             ::LineTo(workRect.right - 1, workRect.bottom -1);
  174.             ::LineTo(workRect.right - 1, workRect.top + kTagHeigth + 1);
  175.             ::MoveTo(workRect.right - 2, workRect.top + kTagHeigth);
  176.             ::LineTo(workRect.left + 1, workRect.top + kTagHeigth);
  177.             
  178.             if (hasColor)
  179.                 {
  180.                     ::ForeColor(whiteColor);
  181.                     ::MoveTo(workRect.left + 1, workRect.bottom - 2);
  182.                     ::LineTo(workRect.left + 1, workRect.top + kTagHeigth + 1);
  183.                     ::LineTo(workRect.right - 3, workRect.top + kTagHeigth + 1);
  184.             
  185.                     ::RGBForeColor(&gAGAColorArray[8]);
  186.                     ::MoveTo(workRect.left + 2, workRect.bottom);
  187.                     ::LineTo(workRect.right - 1, workRect.bottom);
  188.                     ::MoveTo(workRect.right, workRect.bottom - 1);
  189.                     ::LineTo(workRect.right, workRect.top + kTagHeigth + 2);
  190.             
  191.                     ::RGBForeColor(&gAGAColorArray[4]);
  192.                     ::MoveTo(workRect.left + 2, workRect.bottom - 2);
  193.                     ::LineTo(workRect.right - 2, workRect.bottom - 2);
  194.                     ::LineTo(workRect.right - 2, workRect.top + kTagHeigth + 1);
  195.                 }
  196.     
  197.             //    Then let's draw the tab index frames
  198.             short theLeft = workRect.left + 3;
  199.             short theTop = workRect.top + 1;
  200.             short theRight;
  201.             short theWidth;
  202.             short theTextPos;
  203.             short insideColor;
  204.             short color;
  205.             Rect r;
  206.             
  207.             for (int i = 0;i < mTabNumber; i++)
  208.                 {
  209.                     theWidth = mTabTitleWidth[i];
  210.                     if ((theLeft + theWidth) > workRect.right)                    //    Limit the number of tabs if not enough room to display them
  211.                         {
  212.                             mTabNumber = i;
  213.                             break;
  214.                         }
  215.                     theRight = theLeft + theWidth;
  216.                     //    Fill the background
  217.                     PolyHandle thePoly = ::OpenPoly();
  218.                     ::MoveTo(theLeft + 1, theTop + kTagHeigth - 1);
  219.                     ::LineTo(theLeft + 7, theTop + 1);
  220.                     ::LineTo(theRight - 9,theTop + 1);
  221.                     ::LineTo(theRight - 1, theTop + kTagHeigth - 1);
  222.                     ::LineTo(theLeft + 1, theTop + kTagHeigth - 1);
  223.                     ::ClosePoly();
  224.                     if (hasColor)
  225.                         if (i == mSelectedTab)
  226.                             ::RGBBackColor(&gAGAColorArray[2]);
  227.                         else
  228.                             ::RGBBackColor(&gAGAColorArray[4]);
  229.                     ::ErasePoly(thePoly);
  230.                     ::KillPoly(thePoly);
  231.                     //    Draw the frame
  232.                     ::ForeColor(blackColor);
  233.                     ::MoveTo(theLeft, theTop + kTagHeigth - 1);
  234.                     ::Line(0, -1);
  235.                     for (register int i = 0; i < 5; i++)
  236.                         {
  237.                             ::Move(1, -1);
  238.                             ::Line(0, -2);
  239.                         }
  240.                     ::Line(3, -3);
  241.                     ::MoveTo(theRight - 9, theTop);
  242.                     ::Line(3, 3);
  243.                     ::Line(0, 2);
  244.                     for (register int i = 0; i < 4; i++)
  245.                         {
  246.                             ::Move(1, 1);
  247.                             ::Line(0, 2);
  248.                         }
  249.                     ::Move(1, 1);
  250.                     ::Line(0, 1);
  251.                     ::ForeColor(whiteColor);
  252.                     ::MoveTo(theLeft + 1, theTop + kTagHeigth - 1);
  253.                     ::Line(0, -1);
  254.                     for (register int i = 0; i < 5; i++)
  255.                         {
  256.                             ::Move(1, -1);
  257.                             ::Line(0, -2);
  258.                         }
  259.                     ::Line(2, -2);
  260.                     if (hasColor)
  261.                         {
  262.                             ::RGBForeColor(&gAGAColorArray[8]);
  263.                             ::MoveTo(theRight - 9, theTop + 1);
  264.                             ::Line(2, 2);
  265.                             ::Line(0, 2);
  266.                             for (register int i = 0; i < 4; i++)
  267.                                 {
  268.                                     ::Move(1, 1);
  269.                                     ::Line(0, 2);
  270.                                 }
  271.                             ::Move(1, 1);
  272.                             ::Line(0, 1);
  273.                             ::MoveTo(theRight - 8, theTop);
  274.                             ::Line(3, 3);
  275.                             ::Line(0, 2);
  276.                             for (register int i = 0; i < 4; i++)
  277.                                 {
  278.                                     ::Move(1, 1);
  279.                                     ::Line(0, 2);
  280.                                 }
  281.                         }
  282.  
  283.                     ::ForeColor(blackColor);
  284.                     ::MoveTo(theLeft + 9, theTop);
  285.                     ::LineTo(theRight - 10, theTop);
  286.                     if (i == mSelectedTab)
  287.                         {
  288.                             if (hasColor)
  289.                                 ::RGBForeColor(&gAGAColorArray[2]);
  290.                             else
  291.                                 ::ForeColor(whiteColor);
  292.                             ::MoveTo(theLeft + 2, theTop + kTagHeigth - 1);
  293.                         }
  294.                     else
  295.                         ::MoveTo(theLeft + 1, theTop + kTagHeigth - 1);
  296.                     ::LineTo(theRight - 2, theTop + kTagHeigth - 1);
  297.                     if (i != mSelectedTab)
  298.                         ::ForeColor(whiteColor);
  299.                     ::MoveTo(theLeft + 2, theTop + kTagHeigth);
  300.                     ::LineTo(theRight - 2, theTop + kTagHeigth);
  301.                     
  302.                     ::ForeColor(whiteColor);
  303.                     ::MoveTo(theLeft + 9, theTop + 1);
  304.                     ::LineTo(theRight - 10, theTop + 1);
  305.  
  306.                     theTextPos = workRect.top + kTagTextPosition;
  307.             
  308.                     //    Draw the Text into the tab
  309.                     DrawText(mTabTitle[i], theLeft, theWidth, theTextPos);
  310.             
  311.                     theLeft += theWidth;
  312.                 }
  313.         }
  314. }
  315.  
  316. void LAGAIndexTab::DrawText (LStr255 &inText, short inLeftBorder, short inTagWidth, short inTextPos)
  317.  
  318. {
  319.     ::ForeColor(blackColor);
  320.     ::MoveTo(inLeftBorder + ((inTagWidth - ::StringWidth(inText)) / 2), inTextPos);
  321.     ::DrawString(inText);
  322. }
  323.  
  324. //-------Utilities--------------------------------------------------------------------------------------------------
  325.  
  326. void LAGAIndexTab::CalculateTitleWidths ()
  327.  
  328. {
  329.     StTextState theTState;
  330.     
  331.     Int16 just = UTextTraits::SetPortTextTraits(mTextTraitsID);
  332.     short theLeft = 0;
  333.     for (int i = 0; i <= mTabNumber; i++)
  334.         {
  335.             mTabTitleWidth[i] = ::StringWidth(mTabTitle[i]) + kTagWidthOffset;
  336.             mTabLeftPositions[i] = theLeft;
  337.             theLeft += mTabTitleWidth[i] + 1;
  338.         }
  339. }
  340.  
  341. void LAGAIndexTab::SetTabTitle (short inTab, LStr255& inTitle)
  342.  
  343. {
  344.     if (inTab < mTabNumber)
  345.         {
  346.             mTabTitle[inTab] = inTitle;
  347.             mTabTitleWidth[inTab] = -1;
  348.         }
  349. }
  350.  
  351. void LAGAIndexTab::GetTabTitle (short inTab, LStr255& outTitle)
  352.  
  353. {
  354.     if (inTab < mTabNumber)
  355.         outTitle = mTabTitle[inTab];
  356.     else
  357.         outTitle = "\p";
  358. }
  359.  
  360. Boolean LAGAIndexTab::SetTabCount (short inCount)
  361.  
  362. {
  363.     Boolean result = false;
  364.     
  365.     if (inCount <= kMaxTabs)
  366.         {
  367.             mTabNumber = inCount;
  368.             //    for security reasons, force a recalculation of the index tabs on next redraw
  369.             for (int i = 0;i < kMaxTabs; i++)
  370.                 mTabTitleWidth[i] = -1;
  371.             result = true;
  372.         }
  373.     return(result);
  374. }
  375.  
  376. void LAGAIndexTab::SetSelectedTab (short inTab)
  377.  
  378. {
  379.     if (inTab < mTabNumber)
  380.         {
  381.             if (inTab != mSelectedTab)
  382.                 {
  383.                     mWasSelectedTab = mSelectedTab;
  384.                     mSelectedTab = inTab;
  385.                     
  386.                     Rect tabRect;
  387.                     Point *thePt;
  388.                     ::SetRect(&tabRect, mTabLeftPositions[mWasSelectedTab] - 2, 0,
  389.                                         mTabLeftPositions[mWasSelectedTab] + mTabTitleWidth[mWasSelectedTab] + 3, kTagHeigth + 2);
  390.                     thePt = (Point *)&tabRect;
  391.                     LocalToPortPoint(*thePt);
  392.                     thePt++;
  393.                     LocalToPortPoint(*thePt);
  394.                     InvalPortRect(&tabRect);
  395.                     ::SetRect(&tabRect, mTabLeftPositions[mSelectedTab] - 2, 0,
  396.                                         mTabLeftPositions[mSelectedTab] + mTabTitleWidth[mSelectedTab] + 5, kTagHeigth + 2);
  397.                     thePt = (Point *)&tabRect;
  398.                     LocalToPortPoint(*thePt);
  399.                     thePt++;
  400.                     LocalToPortPoint(*thePt);
  401.                     InvalPortRect(&tabRect);
  402.                     
  403.                     AdaptTab();
  404.                     LCommander::SetUpdateCommandStatus(true);        //    Force the menus to update (in case some menu keep track of our tabs)
  405.                 }
  406.         }
  407. }
  408.  
  409. short LAGAIndexTab::GetSelectedTab ()
  410.  
  411. {
  412.     return(mSelectedTab);
  413. }
  414.  
  415. void LAGAIndexTab::EventMouseUp (const EventRecord &inMouseUp)
  416.  
  417. {
  418.     LView::EventMouseUp(inMouseUp);
  419.     
  420.     Rect theTag;
  421.     Point thePt;
  422.     
  423.     thePt = inMouseUp.where;
  424.     GlobalToPortPoint(thePt);
  425.     PortToLocalPoint(thePt);
  426.     for (int i = 0;i < mTabNumber; i++)
  427.         {
  428.             ::SetRect(&theTag, mTabLeftPositions[i], (mSelectedTab == i) ? 0 : 2, mTabLeftPositions[i] + mTabTitleWidth[i], kTagHeigth);
  429.             if (::PtInRect(thePt, &theTag))
  430.                 {
  431.                     this->SetSelectedTab(i);
  432.                     break;
  433.                 }
  434.         }
  435. }
  436.  
  437. void LAGAIndexTab::AdaptTab (Boolean inRefresh)
  438.  
  439. {
  440.     if (mTabbedViewID)
  441.         {
  442.             LView *theView = (LView *)FindPaneByID(mTabbedViewID);
  443.             if (theView)
  444.                 {
  445.                     SPoint32 theUnit;
  446.                     
  447.                     theView->GetScrollUnit(theUnit);
  448.                     theView->ScrollImageTo(0, mSelectedTab * theUnit.v, inRefresh);
  449.                 }
  450.         }
  451. }
  452.  
  453. void LAGAIndexTab::FinishCreateSelf ()
  454.  
  455. {
  456.     this->AdaptTab(false);
  457. }
  458.  
  459. //-------LSTRxIndexTabView implementation-----------------------------------------------------------------------------
  460.  
  461. //    begin    <06/04/96    ca>
  462. void LSTRxAGAIndexTab::RegisterClass ()
  463.  
  464. {
  465.     URegistrar::RegisterClass(LSTRxAGAIndexTab::class_ID, (ClassCreatorFunc)LSTRxAGAIndexTab::CreateSTRxAGAIndexTabStream);
  466. }
  467. //    end    <06/04/96    ca>
  468.  
  469. LSTRxAGAIndexTab* LSTRxAGAIndexTab::CreateSTRxAGAIndexTabStream (LStream *inStream)
  470.  
  471. {
  472.     return (new LSTRxAGAIndexTab(inStream));
  473. }
  474.  
  475. //-------Constructors-------------------------------------------------------------------------------------------------
  476.  
  477. LSTRxAGAIndexTab::LSTRxAGAIndexTab (LStream    *inStream) : LAGAIndexTab(inStream)
  478.  
  479. {
  480.     short theSTRxID;
  481.     
  482.     inStream->ReadData(&theSTRxID, sizeof(theSTRxID));
  483.     
  484.     this->InitSTRxIndexTab(theSTRxID);
  485. }
  486.  
  487. void LSTRxAGAIndexTab::InitSTRxIndexTab (short inSTRxID)
  488.  
  489. {
  490.     Handle theHandle = GetResource('STR#', inSTRxID);
  491.     if (theHandle)
  492.         {
  493.             short theCount = **((short **)theHandle);
  494.             ReleaseResource(theHandle);
  495.             if (theCount > kMaxTabs)
  496.                 theCount = kMaxTabs;
  497.             this->SetTabCount(theCount);
  498.             for (int i = 0;i < theCount; i++)
  499.                 {
  500.                     LStr255 theString;
  501.                     
  502.                     GetIndString(theString, inSTRxID, i + 1);
  503.                     this->SetTabTitle(i, theString);
  504.                 }
  505.         }
  506. }
  507.  
  508.